package com.itheima.wms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.ImmutableMap;
import com.itheima.pinda.exception.BizException;
import com.itheima.wms.common.constants.CodeConstant;
import com.itheima.wms.common.enums.CheckListStatus;
import com.itheima.wms.common.enums.CheckStatus;
import com.itheima.wms.common.enums.CheckTaskStatus;
import com.itheima.wms.common.service.CrudServiceImpl;
import com.itheima.wms.dao.*;
import com.itheima.wms.dto.CheckDTO;
import com.itheima.wms.entity.*;
import com.itheima.wms.factory.CodeWorker;
import com.itheima.wms.service.*;
import com.itheima.wms.vo.BatchVO;
import com.itheima.wms.vo.CheckDetailVO;
import com.itheima.wms.vo.IncreaseDecreaseDetailVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * <p>
 * 业务实现类
 * 盘点单
 * </p>
 */
@Slf4j
@Service
public class CheckServiceImpl extends CrudServiceImpl<CheckMapper, CheckEntity> implements CheckService {

    @Autowired
    private CheckTaskMapper checkTaskMapper;
    @Autowired
    private StatusRecordService statusRecordService;
    @Autowired
    private WarehouseMapper warehouseMapper;
    @Autowired
    private AreaMapper areaMapper;
    @Autowired
    private IncreaseDecreaseService increaseDecreaseService;
    @Autowired
    private OwnerLocationMapper ownerLocationMapper;
    @Autowired
    private StockService stockService;
    @Autowired
    private CheckListService checkListService;

    @Override
    public boolean save(CheckEntity entity) {
        if (null != entity.getOwnerId()) {
            LambdaQueryWrapper<OwnerLocationEntity> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(OwnerLocationEntity::getOwnerId, entity.getOwnerId());
            wrapper.last("limit 1");
            OwnerLocationEntity ownerLocationEntity = ownerLocationMapper.selectOne(wrapper);
            entity.setWarehouseId(ownerLocationEntity.getWarehouseId());
        }
        boolean result = super.save(entity);
        CheckEntity dbEntity = this.getById(entity.getId());
        statusRecordService.saveStatus(dbEntity);
        return result;
    }

    @Override
    @Transactional
    public BatchVO task(List<Long> ids) {
        BatchVO.BatchVOBuilder batchVOBuilder = BatchVO.builder();
        ids.forEach(id -> {
            CheckEntity checkEntity = this.getById(id);
            if (null == checkEntity) {
                log.info("id:{} 未找到", id);
                return;
            }

            // 校验清单是否有未填写的
            LambdaQueryWrapper<CheckListEntity> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(CheckListEntity::getMasterId, id);
            List<CheckListEntity> checkListEntities = checkListService.list(wrapper);
            checkListEntities = checkListEntities.stream().filter(item -> (null != item.getStockNum() && 0 != item.getStockNum())).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(checkListEntities)) {
                log.info("id:{} 清单未填写完成", id);
                batchVOBuilder.error(checkEntity.getCode() + "未完成盘点单清单");
                return;
            }

            if (CheckStatus.NEW.getCode() != checkEntity.getStatus()) {
                log.info("id:{} 状态不符 status:{}", id, checkEntity.getStatus());
                batchVOBuilder.error(checkEntity.getCode() + "状态不合法");
                return;
            }

            LambdaQueryWrapper<CheckTaskEntity> checkTaskWrapper = new LambdaQueryWrapper<>();
            checkTaskWrapper.eq(CheckTaskEntity::getMasterId, checkEntity.getId());
            int cou = checkTaskMapper.selectCount(checkTaskWrapper);
            if (cou > 1) {
                log.info("id:{} 已生成盘点任务", id);
                batchVOBuilder.error(checkEntity.getCode() + "已生成盘点任务");
                return;
            }
            // 修改盘点单状态 为 一盘中
            checkEntity.setStatus(CheckStatus.CHECK.getCode());
            this.updateById(checkEntity);
            statusRecordService.saveStatus(checkEntity);

            // 查询清单统计总库存
            QueryWrapper<CheckListEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("IFNULL(sum(stock_num),0) as totalNum")
                    .eq("master_id", checkEntity.getId());

            Map<String, Object> map = checkListService.listMaps(queryWrapper).get(0);
            Integer totalNum = ((java.math.BigDecimal) map.get("totalNum")).intValue();


            // 生成盘点任务
            CheckTaskEntity checkTaskEntity = new CheckTaskEntity();
            BeanUtils.copyProperties(checkEntity, checkTaskEntity);
            checkTaskEntity.setPlanTaskTime(checkEntity.getPlanCheckTime());
            checkTaskEntity.setMasterId(checkEntity.getId());
            checkTaskEntity.setCode(CodeWorker.nextCode(CodeConstant.CHECKTASK));
            checkTaskEntity.setCheckCode(checkEntity.getCode());
            checkTaskEntity.setStockTotal(totalNum);  //库存总数
            checkTaskEntity.setCheckNum(CheckListStatus.CHECK.getCode());  //一盘
            checkTaskEntity.setStatus(CheckTaskStatus.NEW.getCode());  //初始状态
            checkTaskEntity.setId(null);
            checkTaskMapper.insert(checkTaskEntity);
            statusRecordService.saveStatus(checkTaskEntity);

            batchVOBuilder.result(checkTaskEntity.getCode());
        });
        return batchVOBuilder.build();
    }

    @Override
    public CheckDetailVO getDetail(Long id) {
        CheckDetailVO checkDetailVO = new CheckDetailVO();
        CheckEntity checkEntity = this.getById(id);
        BeanUtils.copyProperties(checkEntity, checkDetailVO);
        LambdaQueryWrapper<CheckTaskEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CheckTaskEntity::getMasterId, checkEntity.getId());

        // 状态变更时间
        List<String> timeArray = statusRecordService.listTime(checkEntity.getId());
        checkDetailVO.setTimeArray(timeArray);
        // 仓库名称
        WarehouseEntity warehouseEntity = warehouseMapper.selectById(checkEntity.getWarehouseId());
        checkDetailVO.setWarehouseName(warehouseEntity.getName());
        // 库区名称
        AreaEntity areaEntity = areaMapper.selectById(checkEntity.getAreaId());
        checkDetailVO.setAreaName(areaEntity == null ? "" : areaEntity.getName());

        // 盘点任务
        List<CheckTaskEntity> checkTasks = checkTaskMapper.selectList(wrapper);
        for (CheckTaskEntity checkTask : checkTasks) {
            if (1 == checkTask.getCheckNum()) {
                // 一盘
                List<IncreaseDecreaseDetailVO> increaseDecreaseEntities = increaseDecreaseService.listDetail((ImmutableMap.of("taskCode", checkTask.getCode())));
                if (!CollectionUtils.isEmpty(increaseDecreaseEntities)) {
                    checkDetailVO.setId1Money(increaseDecreaseEntities.stream().filter(item -> item.getIdMoney() != null).map(IncreaseDecreaseEntity::getIdMoney).reduce(BigDecimal.ZERO, BigDecimal::add));
                    checkDetailVO.setId1List(increaseDecreaseEntities);
                }
                checkDetailVO.setCheckTaskEntity1(checkTask);
            } else {
                // 复盘
                List<IncreaseDecreaseDetailVO> increaseDecreaseEntities = increaseDecreaseService.listDetail(ImmutableMap.of("taskCode", checkTask.getCode()));
                if (!CollectionUtils.isEmpty(increaseDecreaseEntities)) {
                    checkDetailVO.setId2Money(increaseDecreaseEntities.stream().filter(item -> item.getIdMoney() != null).map(IncreaseDecreaseEntity::getIdMoney).reduce(BigDecimal.ZERO, BigDecimal::add));
                    checkDetailVO.setId2List(increaseDecreaseEntities);
                }
                checkDetailVO.setCheckTaskEntity2(checkTask);
            }
        }

        // 盘点清单 总计
        LambdaQueryWrapper<CheckListEntity> checkListWrapper = new LambdaQueryWrapper<>();
        checkListWrapper.eq(CheckListEntity::getMasterId, checkEntity.getId());
        if (null == checkDetailVO.getCheckTaskEntity2()) {
            checkListWrapper.eq(CheckListEntity::getStatus, CheckListStatus.CHECK.getCode()); // 查询一盘
        } else {
            checkListWrapper.eq(CheckListEntity::getStatus, CheckListStatus.RECHECK.getCode()); // 查询复盘
        }
        List<CheckListEntity> checkListEntities = checkListService.list(checkListWrapper);
        checkDetailVO.setLocationTotal(checkListEntities.size());
        checkDetailVO.setGoodsTotal(checkListEntities.stream().mapToInt(CheckListEntity::getStockNum).sum());


        return checkDetailVO;
    }

    @Override
    public IPage<CheckDetailVO> pageDetail(Page<CheckDetailVO> page, Map data) {
        IPage<CheckDetailVO> iPage = this.baseMapper.selectCheckDetail(page, data);
        return iPage;
    }

    @Override
    @Transactional
    public Long generatorCheck(AreaEntity areaEntity) {
        CheckEntity checkEntity = new CheckEntity();
        checkEntity.setStatus(CheckStatus.NEW.getCode());
        checkEntity.setAreaId(null);
        checkEntity.setCode(CodeWorker.nextCode(CodeConstant.CHECK));
        checkEntity.setDimension("KW");
        checkEntity.setOwnerId(null);
        checkEntity.setPlanCheckTime(LocalDateTime.now().withMinute(0).withSecond(0).minusSeconds(0));
        checkEntity.setReason("GH");
        checkEntity.setType("JHPD");
        checkEntity.setWarehouseId(areaEntity.getWarehouseId());
        checkEntity.setAreaId(areaEntity.getId());
        this.save(checkEntity);

        LambdaQueryWrapper<StockEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StockEntity::getAreaId, areaEntity.getId());
        List<StockEntity> stockEntities = stockService.list(wrapper);
        log.info("自动生成盘点单 全部库存:{}", stockEntities);
        List<CheckListEntity> checkListEntities = new ArrayList<>();
        // 遍历生成清单
        stockEntities.forEach(stockEntity -> {
            CheckListEntity checkListEntity = new CheckListEntity();
            checkListEntity.setMasterId(checkEntity.getId());
            checkListEntity.setStatus(CheckListStatus.CHECK.getCode());
            checkListEntity.setStockId(stockEntity.getId());
            checkListEntity.setStockNum(stockEntity.getTotal());
            checkListEntities.add(checkListEntity);
            // 盘点中需要冻结库存
            stockEntity.setFrozen(stockEntity.getTotal());
            stockEntity.setFree(0);
        });

        checkListService.saveBatch(checkListEntities);
        stockService.updateBatchById(stockEntities);
        return checkEntity.getId();
    }

    @Override
    @Transactional
    public void cancel(CheckDTO data) {
        CheckEntity checkEntity = this.getById(data.getId());
        if (null == checkEntity) {
            throw new BizException("盘点单未找到");
        }
        if (checkEntity.getStatus() != CheckStatus.NEW.getCode()) {
            throw new BizException("只能取消新建的盘点单");
        }
        checkEntity.setStatus(CheckStatus.CANCEL.getCode());
        this.updateById(checkEntity);
        statusRecordService.saveStatus(checkEntity);

        LambdaQueryWrapper<CheckListEntity> checkListWrapper = new LambdaQueryWrapper<>();
        checkListWrapper.eq(CheckListEntity::getMasterId, checkEntity.getId());
        checkListWrapper.eq(CheckListEntity::getStatus, CheckListStatus.CHECK.getCode()); // 查询一盘即可
        List<CheckListEntity> checkList = checkListService.list(checkListWrapper);
        checkListService.cancelBatch(checkList);

    }
}

